﻿<!DOCTYPE html>
<html>
<head>
	<title>ol-ext: Openlayers feature animation</title>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

	<meta name="description" content="ol.featureAnimation are used to play animations on ol3 maps." />
	<meta name="keywords" content="ol3, animation, drop, slide, throw, fade, bounce, easing" />

	<!-- jQuery -->
	<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.0.min.js"></script>

	<!-- Openlayers -->
    <link rel="stylesheet" href="https://openlayers.org/en/latest/css/ol.css" />
	<script type="text/javascript" src="https://openlayers.org/en/latest/build/ol.js"></script>
	<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL,Object.assign"></script>
	
	<!-- ol-ext -->
	<script type="text/javascript" src="../../dist/ol-ext.js"></script>

	<link rel="stylesheet" href="../style.css" />
	</head>
<body >
	<a href="https://github.com/Viglino/ol-ext" class="icss-github-corner"><i></i></a>

	<a href="../../index.html">
		<h1>ol-ext: Openlayers feature animation</h1>
	</a>
	<p class="info">
		This example show how to use a transparent style to enable feature selection on animation loop.
		<br/>
		It uses an infinite animation loop to animate features on the map. 
		A transparent feature is displayed to enable selection.
	</p>

	<!-- DIV pour la carte -->
	<div id="map" style="width:600px; height:400px;"></div>

	<div class="options">
		<h2>Options:</h2>
		<i>Click on features to stop/start animation...</i>
	</div>
	
	<script type="text/javascript">
	// Layers
	var layer = new ol.layer.Tile({
        title:'terrain-background',
        source: new ol.source.Stamen({ layer: 'terrain' })
	});

	// The map
	var map = new ol.Map
		({	target: 'map',
			view: new ol.View
			({	zoom: 5,
				center: [166326, 5992663]
			}),
			layers: [layer]
		});
	// Change pointer over feature
	map.on("pointermove", function (evt) 
	{   var hit = this.forEachFeatureAtPixel(evt.pixel, function(feature, layer) { return true; }); 
        if (hit) this.getViewport().style.cursor = 'pointer';
        else this.getViewport().style.cursor = '';
    });

	// Style to draw the feature
	var color = [0,0,255];
	var fillcolor = [0,0,255,0.3];
	var style = 
	[	new ol.style.Style(
			{	image: new ol.style.Shadow({ radius: 15, }),
				stroke: new ol.style.Stroke({ color: [0,0,0,0.3], width: 2 }),
				fill: new ol.style.Fill({ color: [0,0,0,0.3]}),
				zIndex: -1
			}),
		new ol.style.Style(
			{	image: new ol.style.RegularShape({ radius: 10, radius2: 5, points: 5, fill: new ol.style.Fill({ color: color }) }),
				stroke: new ol.style.Stroke({ color: color, width: 2}),
				fill: new ol.style.Fill({ color: fillcolor })
			})
	];
	style[1].getImage().getAnchor()[1] += 10;

	// Transparent style to handle click on animation
	var transparent = [0,0,0,0.01];
	var filltransparent = [0,0,0,0];
	var transparentStyle = 
	[	new ol.style.Style(
			{	image: new ol.style.RegularShape({ radius: 10, radius2: 5, points: 5, fill: new ol.style.Fill({ color: transparent }) }),
				stroke: new ol.style.Stroke({ color: transparent, width: 2 }),
				fill: new ol.style.Fill({ color: filltransparent})
			})
	];
	transparentStyle[0].getImage().getAnchor()[1] += 10;

	// Intinite loop animation
	var animTab = [];
	var anim = new ol.featureAnimation.Bounce(
		{	duration: 800,
			hiddenStyle: transparentStyle
		});
	// Continune animation if not stop by user
	anim.on('animationend', function(e)
		{	if (!e.user) animTab[e.feature.get('nb')] = vector.animateFeature (e.feature, anim);
		});

	// On select start/stop animation
	var select = new ol.interaction.Select({ hitTolerance: 1 });
	map.addInteraction(select);
	select.on('select', function(e)
	{	if (e.selected.length)
		{	var f = e.selected[0];
			select.getFeatures().clear();
			// Create animation if doesn't exist
			if (!animTab[f.get('nb')])
			{	animTab[f.get('nb')] = vector.animateFeature (f, anim);
			}
			// Stop animation if playing 
			else if (animTab[f.get('nb')].isPlaying())
			{	animTab[f.get('nb')].stop({user: true});
			}
			else 
			{	animTab[f.get('nb')].start();
			}
		}
	});

	// Vector layer
	var source = new ol.source.Vector();
	var vector = new ol.layer.Vector(
	{	source: source,
		style: style
	});
	map.addLayer(vector);

	// Add a feature on the map
	function addFeatureAt(nb, featureType, p)
	{	var f, r = map.getView().getResolution() *10;
		switch (featureType)
		{	case 0:
				f = new ol.Feature(new ol.geom.LineString(
					[	[p[0]-8*r,p[1]-3*r], 
						[p[0]-2*r,p[1]+1*r], 
						[p[0]+2*r,p[1]-1*r], 
						[p[0]+8*r,p[1]+3*r]
					]));
				break;
			case 1:
				f = new ol.Feature(new ol.geom.Polygon(
					[[	[p[0]-4*r,p[1]-2*r], 
						[p[0]+3*r,p[1]-2*r], 
						[p[0]+1*r,p[1]-0.5*r], 
						[p[0]+4*r,p[1]+2*r], 
						[p[0]-2*r,p[1]+2*r], 
						[p[0]-4*r,p[1]-2*r]
					]]));
				break;
			default:
				f = new ol.Feature(new ol.geom.Point(p));
				break;
		}
		f.set("nb", nb);
		vector.getSource().addFeature(f);
	}

	// Add 10 random features
	function add10()
	{	// Clear and end animation loop
		vector.getSource().clear();
		select.getFeatures().clear();
		var ex = map.getView().calculateExtent(map.getSize());
		// Add features after animation ends
		for (var i=0; i<10; i++)
		{	addFeatureAt( i, Math.round(Math.random()*3),
					[	ex[0] +Math.random()*(ex[2]-ex[0]),
						ex[1] +Math.random()*(ex[3]-ex[1])
					]);
		};
	}
	add10();

	</script>
	
</body>
</html>